﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace TouchControls
{
    [TemplateVisualState(GroupName = "ExpansionStates", Name = "Expanded"),
     TemplateVisualState(GroupName = "ExpansionStates", Name = "Collapsed"),
     TemplateVisualState(Name = "HasItems", GroupName = "HasItemsStates"),
     TemplateVisualState(Name = "NoItems", GroupName = "HasItemsStates")]
    public class NetworkTree : ItemsControl
    {


        #region ctor
        public NetworkTree()
        {
            this.DefaultStyleKey = typeof(NetworkTree);
        }

        #endregion ctor

        #region overrides
        protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);
            this.HasItems = this.Items.Count > 0;
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            //FrameworkElement elt = this.GetTemplateChild("NetworkTreeContent") as FrameworkElement;
            //UIElement _btn = elt.FindName("btnEdxpand") as UIElement;
            //ParentTree = getParentNetworkTree();

            //_btn.MouseLeftButtonDown += new MouseButtonEventHandler(ExpandTreeLevel);
        }
        #endregion overrides


        #region implementation

        private NetworkTree getParentNetworkTree()
        {
            DependencyObject o = VisualTreeHelper.GetParent(this);
            while (!(o is NetworkTree))
            {
                o = VisualTreeHelper.GetParent(o);
                if (o == null) break;
            }
            return (o as NetworkTree);
        }

        public void ExpandAll()
        {
            this.ApplyExpandToAll(true);
        }

        public void CollapseAll()
        {
            this.ApplyExpandToAll(true);
        }

        public void CollapseBrothers()
        {
            var parent = this.FindParent<NetworkTree>();
            if (parent != null)
            {
                var _pnl = parent.GetPanel();
                    //VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(parent.GetTemplateChild("grdPanel"), 1), 0) as
                    //NetworkPanel;

                foreach (FrameworkElement elt in _pnl.Children)
                {
                    var trees = elt.FindDescendants(e => e is NetworkTree);
                    foreach (NetworkTree tree in trees)
                    {
                        if (tree != this && tree.IsExpanded)
                            tree.ApplyExpandToAll(false);
                    }
                }
            }
        }

        private Panel GetPanel()
        {
            var elt = GetTemplateChild("ItemsHost");
            var childs = VisualTreeHelper.GetChildrenCount(elt);
            if (childs == 0) return null;

            Panel _pnl = VisualTreeHelper.GetChild(elt, 0) as Panel;
            return _pnl;
        }

        private void ApplyExpandToAll(bool isexpanded)
        {
            if (IsExpanded == isexpanded) return;

            IsExpanded = isexpanded;
            var _pnl = GetPanel();
                    //VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.GetTemplateChild("grdPanel"), 1), 0) as
                    //NetworkPanel;
            if (_pnl == null)
                return;
            
            foreach (FrameworkElement elt in _pnl.Children)
            {
                var trees = elt.FindDescendants(e => e is NetworkTree);
                foreach (NetworkTree tree in trees)
                {
                    tree.ApplyExpandToAll(isexpanded);
                }
            }

            //this.UpdateVisualStates(false);
            //this.UpdateLayout();
        }
        
        private void ExpandTreeLevel(object sender, MouseButtonEventArgs e)
        {
            this.Toggle();
        }

        public void Toggle()
        {
            this.IsExpanded = !this.IsExpanded;
            if ((this.IsExpanded) && (this.ParentTree != null))
            {
                NetworkPanel _pnl =
                    VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.ParentTree.GetTemplateChild("grdPanel"), 1), 0) as
                    NetworkPanel;
                foreach (DependencyObject elm in _pnl.Children)
                {
                    var childElt = VisualTreeHelper.GetChild(elm, 0);
                    var tree = childElt as NetworkTree;
                    if ((tree != null) && (tree != this) && (tree.IsExpanded))
                    {
                        tree.ExpandTreeLevel(tree, null);
                    }
                }
            }

            //this.UpdateVisualStates(false);
        }

        private void UpdateVisualStates(bool useTransitions)
        {
            if (this.IsExpanded)
                VisualStateManager.GoToState(this, "Expanded", useTransitions);
            else
                VisualStateManager.GoToState(this, "Collapsed", useTransitions);
            if (this.HasItems)
                VisualStateManager.GoToState(this, "HasItems", useTransitions);
            else
                VisualStateManager.GoToState(this, "NoItems", useTransitions);
        }

        #endregion implementation


        #region DP
        public bool HasItems
        {
            get { return (bool)GetValue(HasItemsProperty); }
            set { SetValue(HasItemsProperty, value); }
        }



        public Visibility HasItemsVisibility
        {
            get { return (Visibility)GetValue(HasItemsVisibilityProperty); }
            set { SetValue(HasItemsVisibilityProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HasItemsVisibility.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HasItemsVisibilityProperty =
            DependencyProperty.Register("HasItemsVisibility", typeof(Visibility), typeof(NetworkTree), new PropertyMetadata(Visibility.Collapsed));        

        public bool IsExpanded
        {
            get
            {
                return (bool)GetValue(IsExpandedProperty);
            }
            set
            {
                var gridPnl = (Grid)this.GetTemplateChild("grdPanel");
                
                SetValue(IsExpandedProperty, value);

                if (value)
                {
                    CollapseBrothers();
                    gridPnl.Visibility = Visibility.Visible;
                    
                    this.UpdateVisualStates(false);                    
                    UpdateLayout();
                }
                else
                {
                    gridPnl.Visibility = Visibility.Collapsed;
                }
            }
        }

        public NetworkTree ParentTree
        {
            get { return (NetworkTree)GetValue(ParentTreeProperty); }
            set { SetValue(ParentTreeProperty, value); }
        }

        public CornerRadius CornerRadius
        {
            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }

        public double LineThickness
        {
            get { return (double)GetValue(LineThicknessProperty); }
            set { SetValue(LineThicknessProperty, value); }
        }

        public Brush LineBrush
        {
            get { return (Brush)GetValue(LineBrushProperty); }
            set { SetValue(LineBrushProperty, value); }
        }



        public ControlTemplate NodeContentTemplate
        {
            get { return (ControlTemplate)GetValue(NodeContentTemplateProperty); }
            set { SetValue(NodeContentTemplateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for NodeContentTemplate.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty NodeContentTemplateProperty =
            DependencyProperty.Register("NodeContentTemplate", typeof(ControlTemplate), typeof(NetworkTree), null);

        

        // Using a DependencyProperty as the backing store for LineBrush.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LineBrushProperty =
            DependencyProperty.Register("LineBrush", typeof(Brush), typeof(NetworkTree), new PropertyMetadata(new SolidColorBrush(Colors.LightGray)));        

        // Using a DependencyProperty as the backing store for LineThickness.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LineThicknessProperty =
            DependencyProperty.Register("LineThickness", typeof(double), typeof(NetworkTree), new PropertyMetadata(2.0));        

        // Using a DependencyProperty as the backing store for CornerRadius.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(NetworkTree), null);        

        public static readonly DependencyProperty HasItemsProperty =
           DependencyProperty.Register("HasItems", typeof(bool), typeof(NetworkTree), null);
        public static readonly DependencyProperty IsExpandedProperty =
            DependencyProperty.Register("IsExpanded", typeof(bool), typeof(NetworkTree), null);
        public static readonly DependencyProperty ParentTreeProperty =
            DependencyProperty.Register("ParentTree", typeof(NetworkTree), typeof(NetworkTree), null);

        #endregion DP


    }
}
